<?php

/**
 * Подсвечивает указанные слова в строке.
 *
 * @access  public
 * @param   string  $string
 * @param   array   $words
 * @param   integer $length
 * @return  string
 */
function smarty_modifier_highlight($string, $words, $length = 0)
{
    if (empty($words)) return $string;

    if ($length > 0)
    {
        // извлекаем из строки фрагменты, содержащие слова, которые нужно подсветить
        $string = smarty_modifier_highlight_trim($string, $words, $length);
    }

    // убираем из текста все тэги в массив $tagList
    preg_match_all('/<[^>]*>/', $string, $tags);

    $tags = array_unique($tags[0]);

    $tagList = array();

    $i = 0;

    foreach ($tags as $tag)
    {
        $tagList[$i] = $tag;
        $string = str_replace($tag, '<' . $i . '>', $string);
        $i++;
    }

    // обрамляем текст <span>-ами
    foreach ($words + array('span') as $word)
    {
        $string = preg_replace('/' . preg_quote($word) . '/ui', '<span class="highlight">$0</span>', $string);
    }

    // возвращаем все тэги на место
    foreach ($tagList as $k=>$i)
    {
         $string = str_replace('<' . $k . '>', $i, $string);
    }

    return $string;
}

/**
 * Обрезает строку до указанной длины таким образом, что в нее попадают слова,
 * которые нужно подсветить.
 *
 * @access  public
 * @param   string  $string
 * @param   array   $words
 * @param   integer $length
 * @return  string
 */
function smarty_modifier_highlight_trim($string, $words, $length)
{
    $encoding = 'utf-8';

    if (mb_strlen($string) > $length)
    {
        $places = array();

        foreach($words as $word)
        {
            $tmp = mb_strtolower($string, $encoding);
            $found_in = mb_strpos($tmp, $word, null, $encoding);
            $sum = - mb_strlen($word, $encoding);

            while (!($found_in ==''))
            {
                $pos = $found_in+mb_strlen($word, $encoding);
                $sum += $pos;  //FIX!!
                $tmp = mb_substr($tmp, $pos, null, $encoding);
                $places[] = $sum;
                $found_in = mb_strpos($tmp, $word, null, $encoding);
            }
        }
        sort($places);
        $x = 0;
        $begin = 0;

        foreach ($places as $id => $place)
        {
            while (array_key_exists($id + $x, $places) && $places[$id + $x] - $place < $length && $x+$id < count($places) && $place < mb_strlen($string, $encoding) -$length) {
                $x++;
                $begin = $id;
            }
        }

        $begin_pos = max(0, isset($places[$begin]) ? $places[$begin] : 0 - 30);
        $string = mb_substr($string, $begin_pos, $length, $encoding);

        if (isset($places[$begin]) && $places[$begin] > 0)
        {
            $begin_pos = mb_strpos($string, ' ', null, $encoding);
        }

        $string = mb_substr($string, $begin_pos, $length, $encoding);

        $string = mb_substr($string, 0, mb_strrpos($string, ' ', null), $encoding);
    }

    return $string;
}
